﻿/// <reference path="../../release/jsApp.js"/>

function NavigationController(app, controllerTypes)
{
	NavigationController.$baseConstructor.call(this);

	this.controllerTypes = controllerTypes || [];

	this.app = app;
	this.currentPath = null;
	this.masterController = null;
	this.backHistory = [];
	this.forwardHistory = [];
}
NavigationController.extend(ASObject, { type: 'AjaxStack.NavigationController' },
	function(p)
	{
		p.getControllers = function()
		{
			if (!this.masterController) return [];
			var all = [this.masterController];
			if (this.masterController.getControllers)
			{
				A.merge(all, this.masterController.getControllers());
			}
			return all;
		}

		p.getCurrentPath = function()
		{
			return this.currentPath;
		}

		p.getBackHistory = function()
		{
			return this.backHistory;
		}

		p.getForwardHistory = function()
		{
			return this.forwardHistory;
		}

		p.registerPath = function(path, fromHistory)
		{
			if (!path) return;
			if (!fromHistory)
			{
				this.backHistory.push(path);
				this.forwardHistory = [];
			}
		}

		p.loadPath = function(path, fromHistory)
		{
			this.log.debug("NAV: this.loadPath(): " + path);
			if (!path) return;

			this.registerPath(this.currentPath, fromHistory);

			this.currentPath = path = Path.getPath(path);

			var controllerCtor = this.masterController
				? this.masterController.constructor.getController(path.getName())
				: null;

			if (controllerCtor)
			{
				this.masterController.loadPath(path);
			}
			else
			{
				var ctor = null;
				for (var i = 0, len = this.controllerTypes.length; i < len; i++)
				{
					var controllerType = this.controllerTypes[i];
					if (controllerType.canHandlePath(path))
					{
						this.log.debug("Loading masterController: " + controllerType.getType() + " with path: " + path);
						this.masterController = new controllerType(this.app);
						this.masterController.loadPath(path); //calls onLoadBody
						break;
					}
				}
				if (!ctor)
				{
					this.log.debug("Could not find masterController for path: " + path);
				}
			}

			this.app.dispatchEvent("onAfterLoadPath", this, path);
		}

		p.loadBody = function(controller, bodyPageHtml)
		{
			if (!this.masterController || this.masterController.getTagId()) return;
			$(this.masterController.getTagId()).html(bodyPageHtml);
		}

		//potentially called by <tag />
		p.gotoPath = function(path)
		{
			var selectedHref = path.toHref();
			location.href = selectedHref;

			$(".nav-link").each(function(i)
			{
				if ($(this).attr("href") == selectedHref)
					$(this).addClass("selected");
				else
					$(this).removeClass("selected");
			});

			var nav = AppBase.getNav();

			nav.log.debug("NAV: executing .nav-link: " + path);

			Quirks.forceBlur();

			//Skip loading already loaded page.
			if (nav.masterController && path.equals(nav.masterController.getPath()))
			{
				nav.log.debug("NAV: skipping already loaded path: " + path + " == " + nav.masterController.getPath());
				return;
			}

			nav.loadPath(path);
		}

		//called by <tag />
		p.handlerClickNavLink = function(e)
		{
			e.stopPropagation();
			var selectedHref = $(this).attr("href");
			AppBase.getNav().gotoPath(Path.getPath(selectedHref));
		}

		//called by <tag />
		p.handlerClickActionLink = function(e)
		{
			//we don't want action-links to change the url
			e.stopPropagation();

			var nav = AppBase.getNav();
			var path = Path.getPath($(this).attr("href"));
			nav.log.debug("NAV: executing .action-link: " + path);

			var allControllers = A.cat(
				AppBase.getInstance().getControllers(),
				AppBase.getInstance().getContexts()
			);
			for (var i = 0, len = allControllers.length; i < len; i++)
			{
				var controller = allControllers[i];
				if (controller[path.getName()])
				{
					nav.log.debug("controller .action-link found: " + path.getName() + " on controller: " + controller);

					controller[path.getName()](this, path.getArgs());
				}
			}
		}

		p.onAfterContentLoaded = function(source, args)
		{
			this.log.debug("NAV: onAfterContentLoaded(): " + args.id);
			var rootSel = args.id ? args.id + " " : "";

			$(rootSel + ".nav-link").unbind("click").click(this.handlerClickNavLink);

			//register .action-links to => controller[A#href]([args]) if exists;
			$(rootSel + ".action-link").unbind("click").click(this.handlerClickActionLink);
		}

		p.actionNavBack = function(source, args)
		{
			if (this.backHistory.length == 0) return;

			var popPath = this.backHistory.pop();
			if (this.currentPath)
			{
				this.forwardHistory.push(this.currentPath);
			}
			this.log.debug("actionNavBack: " + popPath);
			this.loadPath(popPath, true);
		}

		p.actionNavForward = function(source, args)
		{
			if (this.forwardHistory.length == 0) return;

			var popPath = this.forwardHistory.pop();
			this.backHistory.push(popPath);

			this.log.debug("actionNavForward: " + popPath);
			this.loadPath(popPath, true);
		}

	}
);
